Profile picture

[Shell Script] 헷갈리는 If문 대괄호([], [[]]) 문법 이해하기

JaehyoJJAng2024년 11월 05일

개요

쉘 스크립트로 자동화 작업을 하다 보면 한 번쯤 마주치는 쉘 스크립트의 기이한 미스터리가 있죠?

바로 if문을 쓸 때마다 등장하는 대괄호의 사용 방식인데요!

# 이런 코드도 있고...
if [ -z "$username" ]; then ...

# 저런 코드도 있고...
if [[ "$?" -ne 0 ]]; then ...

# 심지어 괄호가 아예 없는 코드도?!
if id "$username" &>/dev/null; then ...

"대체 언제 [ .. ]를 쓰고, 언제 [[ .. ]]를 쓰는 거지? 왜 어떤 건 괄호 조차도 없는거야!"

이런 고민을 해보셨다면, 잘 찾아오셨습니다.

오늘은 이 세 가지 방식의 차이점과 각각의 사용법을 속 시원하게 파헤쳐 보겠습니다.


if문의 역할

프로그래밍을 접해보셨다면 if문이 어떤 상황에서 사용하는지는 대강 다 아실거라고 생각합니다.

쉘 스크립트에서의 if문은 뒤에 오는 명령어의 '종료 코드(Exit code)'를 확인 하는 역할을 합니다.

  • 종료 코드 0: 명렁어 성공!
  • 종료 코드 0 이외의 값: 명령어 실패!

if는 명령어가 성공(0)했을 때 then 절을 실행합니다.

우리가 사용하는 [[[ 역시 조건을 평가한 후 성공 또는 실패 코드를 반환하는 '명령어'일 뿐입니다.

이 사실을 인지하고 있으면 모든 것이 훨씬 쉬워집니다.


1. [ ] 단일 대괄호

가장 전톡적이고 기본적인 조건 검사 도구라고 합니다.

test 명령어와 100% 동일하게 작동하며, 오래된 유닉스 시스템부터 최신 리눅스까지 돌아가기 때문에 호환성 이 가장 큰 장점입니다.


특징

  • test 명령어의 단축 표현입니다.
  • 변수는 반드시 큰따옴표(")로 감싸야 안전합니다. (변수가 비어있으면 에러 발생)
  • 파일, 문자열, 숫자 등 기본적인 비교만 가능합니다.
  • AND/OR 연산자로 -a, -o를 사용합니다.

언제 사용할까요?

  • 스크립트가 어떤 쉘 환경에서 실행될지 모를 때 (최고의 호환성이 필요할 때)
  • 간단한 파일 존재 여부나 변수 비교를 할 때

예시 코드

#!/bin/sh

# 사용자가 이름을 입력했는지 확인
read -p "사용자 이름을 입력하세요: " username

if [ -z "$username" ]; then
    echo "오류: 사용자 이름은 비워둘 수 없습니다."
    exit 1
fi

echo "안녕하세요, $username 님!"

잊지 마세요! []는 단어가 아닌 명령어입니다. 따라서 [ "$var" ]처럼 괄호 안쪽에 항상 공백을 넣어주어야 합니다.


2. [[ ]] 이중 대괄호

[[ ]]는 Bash, Zsh 같은 현대적인 쉘이 제공하는 강력하고 향상된 버전의 테스트 기능입니다.

실수를 줄여주고 더 많은 기능을 제공하기 때문에, 특별한 이유가 없다면 가장 추천하는 방식입니다.


특징

  • [ ]의 모든 기능을 포함하며 더 안정적입니다.
  • 변수를 따옴표로 감싸지 않아도 대부분 안전하게 처리됩니다. (그래도 습관적으로 감싸는 게 좋습니다!)
  • &&, || 같은 직관적인 논리 연산자를 사용할 수 있습니다.
  • 패턴 매칭, 정규 표현식 등 고급 문자열 처리가 가능합니다.

언제 사용할까요?

  • 스크립트가 Bash나 Zsh 환경에서 실행될 것이 확실할 때 (사실상 거의 모든 경우)
  • 복잡한 조건을 조합하거나, 특정 패턴으로 문자열을 검사해야 할 때

예시 코드

#!/bin/bash

# 스크립트 인자로 .log 파일이 주어졌는지 확인
if [[ "$1" == *.log && -f "$1" ]]; then
    echo "'$1'은(는) 존재하는 로그 파일입니다."
    echo "내용을 분석합니다..."
else
    echo "오류: 존재하는 .log 파일을 인자로 전달해주세요."
    exit 1
fi

# 이메일 형식 검사 (정규 표현식)
email="test@example.com"
if [[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]]; then
    echo "올바른 이메일 형식입니다."
fi

3. 괄호 없음

if문의 본질을 가장 잘 보여주는 방식이죠.

grep, ping, id 등과 같이 실행 결과만으로 성공/실패를 알 수 있는 명령어는 괄호 없이 직접 사용하여 코드를 훨씬 더 직관적으로 만들 수 있답니다.


특징

  • 명령어의 성공(종료 코드 0) 여부 자체가 조건이 됩니다.
  • 코드가 간결하고, 읽는 사람이 명령어의 역할을 바로 이해할 수 있습니다.
  • "만약 grep으로 단어를 찾는 데 성공했다면..." 처럼 자연스럽게 읽힙니다.

언제 사용할까요?

  • 특정 사용자가 시스템에 존재하는지 확인할 때 (id, getent)
  • 파일 안에 특정 텍스트가 있는지 찾을 때 (grep)
  • 특정 서버가 온라인 상태인지 확인할 때 (ping, nc)

예시 코드

#!/bin/bash

# 1. 'nginx' 사용자가 시스템에 존재하는지 확인
if id "nginx" &>/dev/null; then
    echo "nginx 사용자가 이미 존재합니다."
else
    echo "nginx 사용자를 생성합니다..."
    # useradd nginx
fi

# 2. 설정 파일에 'enabled = true' 항목이 있는지 확인
if grep -q "enabled = true" /etc/myapp/config.conf; then
    echo "애플리케이션이 활성화되어 있습니다. 시작합니다."
    # systemctl start myapp
fi

마무리

Bash 스크립트라면 [[ ]]를 씁시다!

가장 안전하고 제공하는 기능도 많고!

그러나 운영 중인 시스템이 최신 버전과 꽤 벌어져있거나, 스크립트가 아주 오래된 경우라면!

전통적인 []를 사용하는게 안전할 것 같네요!
(차라리 이런 경우라면 스크립트를 처음부터 짤 것 같기는 합니다만)


읽어주셔서 감사합니다.

    Tag -

Loading script...